﻿package systems.traer
{
	import flash.display.BitmapData;
	import flash.display.Sprite;
	import flash.display.TriangleCulling;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.geom.Point;
	import flash.geom.Vector3D;
	import utils.GeomUtils;
	
	
	public class ClothPic extends Sprite 
	{
		
		private var physics:ParticleSystem;
		private var particles:Vector.<Vector.<Particle>>;
		private var gridSize:int = 20;
		
		private const SPRING_STRENGTH:Number = 0.2;
		private const SPRING_DAMPING:Number = 0.1;
		
		private var isDown:Boolean = false;
		private var old:Point = new Point();
		private var corners:Vector.<Particle>;
		
		public function ClothPic():void 
		{
			
			stage.frameRate = 48
			
			physics = new ParticleSystem( new Vector3D( 0, 0, 0.01 ), 0.01 );
			
			particles = new Vector.<Vector.<Particle>>(gridSize, true);
			
			var gridStepX:Number = (stage.stageWidth / 2) / gridSize;
			var gridStepY:Number = (stage.stageHeight / 2) / gridSize;
			
			var i:int,j:int;
			
			var left:Number = stage.stageWidth / 2 - ( ( gridStepX * gridSize ) / 2 );
			var top:Number = stage.stageHeight / 2 - ( ( gridStepY * gridSize ) / 2 );
			
			
			for (i = 0; i < gridSize; i++) 
			{
				particles[i] = new Vector.<Particle>(gridSize, true);
				
				for (j = 0; j < gridSize; j++) 
				{
					particles[i][j] = physics.makeParticle( 1, left + j * gridStepX + (width / 4),  top + i * gridStepY + 20, 0.0);
					if (j > 0) 
					{
						
						physics.makeSpring(particles[i][j - 1], particles[i][j], SPRING_STRENGTH, SPRING_DAMPING, gridStepX);
						
					}
				}
			}
			for (j = 0; j < gridSize; j++) 
			{
				for (i = 1; i < gridSize; i++) 
				{
					 physics.makeSpring(particles[i - 1][j], particles[i][j], SPRING_STRENGTH, SPRING_DAMPING, gridStepY);
				}
			}
			
			
			corners = Vector.<Particle>( [
												particles[0][0], 
												particles[0][gridSize - 1],
												particles[gridSize - 1][0], 
												particles[gridSize - 1][gridSize - 1] 
											] );
			for each( var p:Particle in corners )
			{
				p.fixed = true;
			}
			
			stage.addEventListener(MouseEvent.MOUSE_DOWN, onDown);
			stage.addEventListener(MouseEvent.MOUSE_UP, onUp);
			addEventListener(Event.ENTER_FRAME, draw);
			
			
		}
		
		
		private function onDown(e:MouseEvent):void {
			isDown = true;
		}
		
		private function onUp(e:MouseEvent):void
		{
			
			isDown = false;
			//particles[0][gridSize - 1].velocity.setFromValues( (mouseX - old.x), (mouseY - old.y), 0 );

		}
		private function draw(e:Event = null):void
		{
			
			physics.tick();

			if (isDown)
			{
				var p:Particle = getClosestParticle();
				//particles[0][gridSize - 1].position.setFromValues( mouseX, mouseY, 0);
				p.position.x = mouseX;
				p.position.y = mouseY;
				p.clearVelocity();
			}
			
			graphics.clear();
			graphics.lineStyle(0, 0xffffff);
			var i:int, j:int;
			/*
			for (i = 0; i < gridSize; i++)
			{
				
				for (j = 0; j < gridSize; j++)
				{
					particles[i][j].draw( graphics );
				}
			}
			/*
			for (i = 0; i < gridSize; i++)
			  {
				
				graphics.moveTo(particles[i][0].position.x, particles[i][0].position.y);
				for (j = 0; j < gridSize; j++)
				{
				  graphics.lineTo( particles[i][j].position.x, particles[i][j].position.y);
				}
				graphics.lineTo(particles[i][gridSize - 1].position.x, particles[i][gridSize - 1].position.y);
			  }
			  
			  for (j = 0; j < gridSize; j++)
			  {
				
				graphics.moveTo(particles[0][j].position.x, particles[0][j].position.y);
				for (i = 0; i < gridSize; i++)
				{
				  graphics.lineTo(particles[i][j].position.x, particles[i][j].position.y);
				}
				graphics.lineTo(particles[gridSize - 1][j].position.x, particles[gridSize - 1][j].position.y);
			  }*/
			
			  old.x = mouseX;
			  old.y = mouseY;
			  
			  
			  drawTris();
			  
		}
		
		private function drawTris():void 
		{
			
			var i:int,j:int;
			
			var vertices:Vector.<Number> = new Vector.<Number>();
			var uvs:Vector.<Number> = new Vector.<Number>();
			
			
			var indices:Vector.<int> = new Vector.<int>();
			var v:Vector3D;
			for (i = 0; i < gridSize; i++) 
			{
				for (j = 0; j < gridSize; j++) 
				{
					particles[i][j].draw( graphics );
					
					v = particles[i][j].position;
					
					vertices.push( v.x, v.y, v.z );
					
					uvs.push( i / gridSize, j / gridSize, 0 );
					
				}
			}
			
			
			for (i = 0; i < gridSize * gridSize; i++) 
			{
				var x:int = i % gridSize;
				var y:int = int( i / gridSize );
				
				indices.push( x, x + 1, x + y * gridSize );
				//indices.push( x + 1, x + y * gridSize,  x + y * gridSize );
					
				if ( x < gridSize - 1 && y < gridSize - 1 )
				//if ( i == 0 && j == 0 )
				{
					
				}
				
			}
			
			graphics.beginBitmapFill( new BitmapData(10, 10, false, 0xFF0000 ) );
			graphics.drawTriangles( vertices, indices, uvs );
			
			
		}
		
		private function getClosestParticle():Particle 
		{
			var distMax:Number = Number.POSITIVE_INFINITY;
			var dist:Number;
			var _p:Particle;
			for each( var p:Particle in corners )
			{
				dist = GeomUtils.distance( new Point( p.position.x, p.position.y ), new Point( mouseX, mouseY ) );
				if ( dist < distMax )
				{
					distMax = dist;
					_p = p;
				}
			}
			return _p;
		}
		
		
	}
	
}